package com.yyfax.pay.depository.service.inner.impl;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.enums.FuiouBusiTypeEnum;
import com.yyfax.pay.common.enums.FuiouDepositStateEnum;
import com.yyfax.pay.common.exception.PayExceptionCode;
import com.yyfax.pay.common.model.vo.PayRspCodeVO;
import com.yyfax.pay.common.util.FuiouIdUtils;
import com.yyfax.pay.depository.dao.FuiouTransferMerchantUserDao;
import com.yyfax.pay.depository.dao.FuiouTransferUserUserDao;
import com.yyfax.pay.depository.domain.FuiouTransferMerchantUser;
import com.yyfax.pay.depository.domain.FuiouTransferUserUser;
import com.yyfax.pay.depository.service.inner.FuiouDepositCommonService;
import com.yyfax.pay.depository.service.inner.FuiouTransferService;
import com.yyfax.pay.depository.vo.TransferVO;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouDepositService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouDepositTradeService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouSignService;
import com.yyfax.pay.third.model.to.fuioudeposit.FuiouDepositConfigExt;
import com.yyfax.pay.vo.depository.TransferReq;

/**
 * 富友存管转账划拨service
 *
 * @author yejc
 * @date 2017-09-05
 * @since v1.0.0
 */
@Service
public class FuiouTransferServiceImpl implements FuiouTransferService {

	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Resource
	private FuiouIdUtils fuiouIdUtils;
	@Resource
	private FuiouTransferMerchantUserDao transferMerchantUserDao;
	@Resource
	private FuiouTransferUserUserDao transferUserUserDao;
	@Resource
	private FuiouSignService fuiouSignService;
	@Resource
	private FuiouDepositService fuiouDepositService;
	@Resource
	private FuiouDepositCommonService fuiouDepositCommonService;
	@Resource
	private FuiouDepositTradeService fuiouDepositTradeService;

	@Override
	public FuiouTransferMerchantUser transferMerchantAndUser(TransferReq req, String merchantCode) {
		// 初始化订单或根据orderId和merchantCode查询
		FuiouTransferMerchantUser order = initTransferMerchantUserOrder(req, merchantCode);

		// 更新订单
		int i = transferMerchantUserDao.updateStateByBusiId(FuiouDepositStateEnum.INI.getValue(), FuiouDepositStateEnum.DEALING.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime());
		if (i > 0) {
			// 请求存管系统
			PayRspCodeVO payRspCodeVO = fuiouDepositTradeService.transferMerchantAndUser(order);

			// 处理返回结果
			handleMerchantTransferUser(payRspCodeVO, order);
		}

		// 根据订单最终的状态, 返回响应
		return transferMerchantUserDao.selectByPrimaryKey(order.getBusiId());
	}

	/**
	 * 处理转账结果
	 *
	 * @author yejc
	 * @date 2017-09-30
	 * @since v2.0.0
	 * @param resp
	 * @param order
	 */
	private void handleMerchantTransferUser(PayRspCodeVO resp, FuiouTransferMerchantUser order) {
		final String op = "FuiouTransferServiceImpl.handleMerchantTransferUser";
		// 超时插入查询任务
		if (PayExceptionCode.WARN_REQ_TIME_OUT.isCode(resp.getCode())) {
			logger.warn(Log.op(op).msg("转账(商户与个人之间)请求超时").kv("busiId", order.getBusiId()).toString());
			fuiouDepositCommonService.saveQueryTask(order.getMerchantCode(), order.getBusiId(), FuiouBusiTypeEnum.TRADE_QUERY);
			throw PayExceptionCode.WARN_REQ_TIME_OUT.exp();
		}

		if (PayExceptionCode.SUCCESS.isCode(resp.getCode())) {
			// 更新订单处理状态为成功
			transferMerchantUserDao.updateStateRspByBusiId(FuiouDepositStateEnum.SUCCESS.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime(), resp.getCode(), resp.getDesc());
		} else {
			// 更新订单处理状态为失败
			transferMerchantUserDao.updateStateRspByBusiId(FuiouDepositStateEnum.FAIL.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime(), resp.getCode(), resp.getDesc());
		}
	}

	@Override
	public FuiouTransferUserUser transferUserAndUser(TransferReq req, String merchantCode) {
		// 初始化订单或根据orderId和merchantCode查询
		FuiouTransferUserUser order = initTransferUserOrder(req, merchantCode);

		// 更新订单
		int i = transferUserUserDao.updateStateByBusiId(FuiouDepositStateEnum.INI.getValue(), FuiouDepositStateEnum.DEALING.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime());
		if (i > 0) {
			// 请求存管系统
			PayRspCodeVO payRspCodeVO = fuiouDepositTradeService.transferUserAndUser(order);

			// 处理返回结果
			handleUserTransferUser(payRspCodeVO, order);
		}

		// 根据订单最终的状态, 返回响应
		return transferUserUserDao.selectByPrimaryKey(order.getBusiId());
	}

	/**
	 * 处理划拨结果
	 *
	 * @author yejc
	 * @date 2017-09-30
	 * @since v2.0.0
	 * @param resp
	 * @param order
	 */
	private void handleUserTransferUser(PayRspCodeVO resp, FuiouTransferUserUser order) {
		final String op = "FuiouTransferServiceImpl.handleUserTransferUser";
		// 超时插入查询任务
		if (PayExceptionCode.WARN_REQ_TIME_OUT.isCode(resp.getCode())) {
			logger.warn(Log.op(op).msg("划拨(个人与个人之间)请求超时").kv("busiId", order.getBusiId()).toString());
			fuiouDepositCommonService.saveQueryTask(order.getMerchantCode(), order.getBusiId(), FuiouBusiTypeEnum.TRADE_QUERY);
			throw PayExceptionCode.WARN_REQ_TIME_OUT.exp();
		}

		if (PayExceptionCode.SUCCESS.isCode(resp.getCode())) {
			// 更新订单处理状态为成功
			transferUserUserDao.updateStateRspByBusiId(FuiouDepositStateEnum.SUCCESS.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime(), resp.getCode(), resp.getDesc());
		} else {
			// 更新订单处理状态为失败
			transferUserUserDao.updateStateRspByBusiId(FuiouDepositStateEnum.FAIL.getValue(), order.getBusiId(), DateUtil.getCurrentDateTime(), resp.getCode(), resp.getDesc());
		}
	}

	/**
	 * 初始化订单或根据orderId和merchantCode查询
	 *
	 * @author yejc
	 * @date 2017-09-30
	 * @since v2.0.0
	 * @param req
	 * @param merchantCode
	 * @return
	 */
	private FuiouTransferUserUser initTransferUserOrder(TransferReq req, String merchantCode) {
		final String op = "FuiouTransferServiceImpl.initTransferUserOrder";
		FuiouTransferUserUser order = new FuiouTransferUserUser();
		order.setOrderTime(req.getOrderTime());
		order.setOrderId(req.getOrderId());
		order.setMerchantCode(merchantCode);
		order.setState(FuiouDepositStateEnum.INI.getValue());
		order.setTerminal(req.getTerminal());
		String now = DateUtil.getCurrentDateTime();
		order.setCreateTime(now);
		order.setUpdateTime(now);
		order.setBusiId(fuiouIdUtils.generateBusiId(FuiouBusiTypeEnum.TRANSFER_USER_USER, merchantCode));
		order.setOutAccountNo(req.getOutAccountNo());
		order.setInAccountNo(req.getInAccountNo());
		order.setAmount(req.getAmount());
		order.setContractNo(req.getContractNo());
		order.setRemark(req.getRemark());
		try {
			transferUserUserDao.insert(order);
		}catch (DuplicateKeyException e) {
			logger.warn(Log.op(op).msg("订单已存在！").kv("orderId", req.getOrderId()).kv("merchantCode", merchantCode).toString(), e);
			order = transferUserUserDao.selectByOrderIdMerchantCode(req.getOrderId(), merchantCode);
		}
		return order;
	}

	/**
	 * 封装转账划拨请求参数
	 *  @param extInfo
	 * @param merchantCode
	 * @param busiId
	 * @param outAccountNo
	 * @param inAccountNo
	 * @param amount
	 * @param contractNo
	 * @param remark @return
	 */
	private TransferVO buildTransferReqParams(FuiouDepositConfigExt extInfo, String merchantCode, String busiId, String outAccountNo, String inAccountNo, String amount, String contractNo, String remark) {
		TransferVO vo = new TransferVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(busiId);
		vo.setOutAccountNo(outAccountNo);
		vo.setInAccountNo(inAccountNo);
		vo.setAmount(amount);
		vo.setContractNo(contractNo);
		vo.setRemark(remark);
		vo.setSignature(fuiouSignService.getSign(merchantCode, vo));

		return vo;
	}

	/**
	 * 初始化订单或根据orderId和merchantCode查询
	 *
	 * @author yejc
	 * @date 2017-09-30
	 * @since v2.0.0
	 * @param req
	 * @param merchantCode
	 * @return
	 */
	private FuiouTransferMerchantUser initTransferMerchantUserOrder(TransferReq req, String merchantCode) {
		final String op = "FuiouTransferServiceImpl.initTransferMerchantUserOrder";
		FuiouTransferMerchantUser order = new FuiouTransferMerchantUser();
		order.setOrderTime(req.getOrderTime());
		order.setOrderId(req.getOrderId());
		order.setMerchantCode(merchantCode);
		order.setState(FuiouDepositStateEnum.INI.getValue());
		order.setTerminal(req.getTerminal());
		String now = DateUtil.getCurrentDateTime();
		order.setCreateTime(now);
		order.setUpdateTime(now);
		order.setBusiId(fuiouIdUtils.generateBusiId(FuiouBusiTypeEnum.TRANSFER_MERCHANT_USER, merchantCode));
		order.setOutAccountNo(req.getOutAccountNo());
		order.setInAccountNo(req.getInAccountNo());
		order.setAmount(req.getAmount());
		order.setContractNo(req.getContractNo());
		order.setRemark(req.getRemark());
		try {
			transferMerchantUserDao.insert(order);
		}catch (DuplicateKeyException e) {
			logger.warn(Log.op(op).msg("订单已存在！").kv("orderId", req.getOrderId()).kv("merchantCode", merchantCode).toString(), e);
			order = transferMerchantUserDao.selectByOrderIdMerchantCode(req.getOrderId(), merchantCode);
		}
		return order;
	}
}
